#ifndef N_MD2MODEL_H
#define N_MD2MODEL_H

#include "resource/nresource.h"
#include "kernel/nfileserver2.h"
#include "gfx2/ngfxserver2.h"
#include "gfx2/ndynamicmesh.h"

// Without this the structures get padded out to the next four bytes in size.
#pragma pack(push, 1)

//------------------------------------------------------------------------------
class nMD2Model : public nResource
{
public:
	// MD2 related structures.

    struct MD2Header
    {
		int ident;
		short version;
		short vertexres;

		int skinWidth;
		int skinHeight;
		int frameSize;

		int numSkins;
		int numXYZ;
		int numST;
		int numTriangles;
		int numGLCmds;
		int numFrames;

		int ofsSkins;
		int ofsST;
		int ofsTriangles;
		int ofsFrames;
		int ofsGLCmds;
		int ofsEnd;
    };

    struct MultipleSurfaceHeader
    {
		int numPrims;
		int ofsPrims;
    };

    struct TaggedSurfaceHeader
    {
		int numSurface;
		int ofsSurface;
    };

    struct TLODData
    {
        float scaleFactor[3];
    };

    struct TaggedSurface
    {
		char name[8];
		unsigned int idxTriangle;
    };

    struct MultipleSurface
    {
		short numPrimitives;
    };

	struct SkinName
    {
		char name[64];
    };

	struct FrameVertexData3
    {
		unsigned char v[3];
		unsigned short idxNormal;
    };

	struct FrameVertexData4
    {
		unsigned long v;
		unsigned short idxNormal;
    };

	struct FrameVertexData6
    {
		unsigned short v[3];
		unsigned short idxNormal;
    };

	struct FrameHeader3
    {
        float scaleVector[3];
        float translationVector[3];
		char name[16];
        FrameVertexData3 verts[1];
    };

	struct FrameHeader4
    {
        float scaleVector[3];
        float translationVector[3];
		char name[16];
        FrameVertexData4 verts[1];
    };

	struct FrameHeader6
    {
        float scaleVector[3];
        float translationVector[3];
		char name[16];
        FrameVertexData6 verts[1];
    };

	struct TextureCoordinate
    {
		short u;
		short v;
    };

	struct MD2Triangle
    {
		short idxXYZ[3];
		short idxST[3];
    };

	struct PrimitiveVertex
    {
		float u;
		float v;
		int idxVertex;
    };

	// Local storage/caching structures.

	struct Primitive
	{
		nGfxServer2::PrimitiveType primitiveType;
		int numVertices;
		PrimitiveVertex *vertexInfo;
	};

	struct Vertex
	{
		float xyz[3];
		int idxNormal;
	};

	struct AnimationFrame
	{
		nString *name;
		Vertex *vertices;
	};

    /// constructor
    nMD2Model();
    /// destructor
    virtual ~nMD2Model();

	virtual bool PopulateMesh(nDynamicMesh *dynMesh, int surfaceIdx);
protected:
    /// load mesh resource
    virtual bool LoadResource();
    /// unload mesh resource
    virtual void UnloadResource();

	virtual float CalculateScalar(int v);

    int numVertices;
	int numPrimitives;
	int numFrames;
	int numSurfaces;

	float uScalar;
	float vScalar;

	MultipleSurface *surfaces;
	SkinName *skinNames;
	AnimationFrame *frames;
	Primitive *primitives;
};

#endif

